home *** CD-ROM | disk | FTP | other *** search
- {$S-,R-,V-,I-,B-,F+,O+,A-,X+}
-
- unit DDisk;
- {-Read and write absolute sectors using DOS int $25 and $26
- in protected mode under DOS or Windows. Does not support real mode.
- Requires BP7 or TPW 1.5.
-
- Based on the code in the OPDOS unit from Object Professional.
-
- Thanks to Maynard Riley and Mark Boler for work done on this unit.
-
- Notes:
- The calling parameters correspond to those in OPDOS.
- Drive = 0 corresponds to drive A.
- Sectors are typically 512 bytes each. NumSects*SectorSize must be
- less than 64K.
- Buf may be any buffer in a protected mode program. DDISK
- temporarily allocates a DOS real mode buffer, then copies
- the result into or out of Buf.
- If the function returns False, the DosError variable from the
- DOS or WINDOS unit may have a non-zero value with more information
- about the failure.
-
- Use DPMIWriteDiskSectors with caution!
-
- Version 1.0 (first public release) 7/19/94
-
- For more information, contact TurboPower Software
- CompuServe 76004,2611
- }
-
- interface
-
- function DPMIReadDiskSectors(Drive : Word;
- FirstSect : LongInt; NumSects : Word;
- var Buf) : Boolean;
- {-Read sectors using int $25}
-
- function DPMIWriteDiskSectors(Drive : Word;
- FirstSect : LongInt; NumSects : Word;
- var Buf) : Boolean;
- {-Write sectors using int $26}
-
- {====================================================================}
-
- implementation
-
- uses
- {$IFDEF DPMI}
- DOS,
- {$ELSE}
- WinDOS,
- {$ENDIF}
- WinAPI;
-
- type
- DpmiRealBuf =
- object
-
- private
- Bytes : LongInt;
- BufBase : LongInt;
-
- public
- constructor Init(BufBytes : LongInt);
- destructor Done;
- function Size : LongInt;
- function Segment : Word;
- function Selector : Word;
- function RealPtr : Pointer;
- function ProtPtr : Pointer;
- end;
-
- DPMIRegisters =
- record
- DI : LongInt;
- SI : LongInt;
- BP : LongInt;
- Reserved : LongInt;
- BX : LongInt;
- DX : LongInt;
- CX : LongInt;
- AX : LongInt;
- Flags : Word;
- ES : Word;
- DS : Word;
- FS : Word;
- GS : Word;
- IP : Word;
- CS : Word;
- SP : Word;
- SS : Word;
- end;
-
- PacketPtr = ^PacketRec;
- PacketRec =
- record
- StartLo : Word;
- StartHi : Word;
- Count : Word;
- BufOfs : Word;
- BufSeg : Word;
- end;
-
- procedure GetRealModeIntVector(IntNo : Byte; var Vector : Pointer); assembler;
- asm
- mov ax,0200h
- mov bl,IntNo
- int 31h
- les di,Vector
- mov word ptr es:[di],dx
- mov word ptr es:[di+2],cx
- end;
-
- function CallFarRealModeProc(var Regs : DPMIRegisters) : Word; assembler;
- asm
- mov ax,0301h
- xor bx,bx
- xor cx,cx
- les di,Regs
- int 31h
- jc @@9
- xor ax,ax
- @@9:
- end;
-
- function DpmiRealBuf.Segment : Word;
- begin
- Segment := BufBase shr 16;
- end;
-
- function DpmiRealBuf.Selector : Word;
- begin
- Selector := BufBase and $FFFF;
- end;
-
- function DpmiRealBuf.RealPtr : Pointer;
- begin
- RealPtr := Ptr(BufBase shr 16, 0);
- end;
-
- function DpmiRealBuf.ProtPtr : Pointer;
- begin
- ProtPtr := Ptr(BufBase and $FFFF, 0);
- end;
-
- function DpmiRealBuf.Size : LongInt;
- begin
- Size := Bytes;
- end;
-
- constructor DpmiRealBuf.Init(BufBytes : LongInt);
- begin
- BufBase := GlobalDosAlloc(BufBytes);
- if BufBase = 0 then
- Fail;
- Bytes := BufBytes;
- end;
-
- destructor DpmiRealBuf.Done;
- begin
- GlobalDosFree(Selector);
- end;
-
- type
- DiskInfoRec =
- object
- DriveNumber : Byte;
- ClustersAvailable : Word;
- TotalClusters : Word;
- BytesPerSector : Word;
- SectorsPerCluster : Word;
- constructor Init(d : Byte);
- end;
-
- constructor DiskInfoRec.Init(d : Byte);
- var
- Ok : Boolean;
- begin
- DriveNumber := d; { 0 = default ; 1 = 'A' }
-
- asm
- mov dl,d
- mov ah,$36
- int $21
- cmp ax,$FFFF
- je @8
-
- les di,Self
- mov es:[di].SectorsPerCluster,ax
- mov es:[di].ClustersAvailable,bx
- mov es:[di].BytesPerSector,cx
- mov es:[di].TotalClusters,dx
- mov al,True
- jmp @9
-
- @8: mov al,False
- @9: mov Ok,al
- end;
-
- if not Ok then
- Fail;
- end;
-
- function DPMIReadWrite(Drive : Word;
- FirstSect : LongInt; NumSects : Word;
- var Buf; Vector : Byte) : Boolean;
- var
- SaveInt : Pointer;
- Status : Word;
- BufBytes : LongInt;
- DiskInfo : DiskInfoRec;
- InterimBuf : DpmiRealBuf;
- PacketBuf : DpmiRealBuf;
- Regs : DPMIRegisters;
- begin
- DosError := 0;
- DPMIReadWrite := False;
-
- if not DiskInfo.Init(Drive+1) then
- Exit;
-
- BufBytes := LongInt(NumSects)*DiskInfo.BytesPerSector;
- if BufBytes > 65535 then
- Exit;
- if not InterimBuf.Init(BufBytes) then
- Exit;
-
- if not PacketBuf.Init(SizeOf(PacketRec)) then begin
- InterimBuf.Done;
- Exit;
- end;
-
- if Vector = $26 then
- Move(Buf, InterimBuf.ProtPtr^, BufBytes);
-
- FillChar(Regs, SizeOf(Regs), 0);
- with PacketPtr(PacketBuf.ProtPtr)^ do begin
- StartLo := FirstSect and $FFFF;
- StartHi := FirstSect shr 16;
- Count := NumSects;
- BufOfs := 0;
- BufSeg := InterimBuf.Segment;
- end;
-
- GetRealModeIntVector(Vector, SaveInt); { returns real mode seg:ofs }
- with Regs do begin
- CX := $FFFF;
- AX := Drive;
- BX := 0;
- DS := PacketBuf.Segment;
- CS := LongInt(SaveInt) shr 16;
- IP := LongInt(SaveInt) and $FFFF;
- end;
- Status := CallFarRealModeProc(Regs);
-
- if Status = 0 then
- if Odd(Regs.Flags) then
- DosError := Regs.AX
- else begin
- if Vector = $25 then
- Move(InterimBuf.ProtPtr^, Buf, BufBytes);
- DPMIReadWrite := True;
- end;
-
- PacketBuf.Done;
- InterimBuf.Done;
- end;
-
- function DPMIReadDiskSectors(Drive : Word;
- FirstSect : LongInt; NumSects : Word;
- var Buf) : Boolean;
- begin
- DPMIReadDiskSectors := DPMIReadWrite(Drive, FirstSect, NumSects, Buf, $25);
- end;
-
- function DPMIWriteDiskSectors(Drive : Word;
- FirstSect : LongInt; NumSects : Word;
- var Buf) : Boolean;
- begin
- DPMIWriteDiskSectors := DPMIReadWrite(Drive, FirstSect, NumSects, Buf, $26);
- end;
-
- end.